import datetime

from abc import ABC, abstractmethod
from logging import Logger

from kubernetes import config as kube_config, client

core_api: client.CoreV1Api = client.CoreV1Api()

from utils.spec import *

g_component = None
g_host = None


def post_event(namespace: str, obj_ref: dict, type: str, action: str, reason: str, msg: str) -> None:
    if len(msg) > 1024:
        msg = msg[:1024]

    body = {
        'action': action,
        'eventTime': datetime.datetime.now().isoformat() + 'Z',
        'involvedObject': obj_ref,
        'message': msg,
        'metadata': {
            'namespace': namespace,
            'generateName': 'reconciler-evt-'
        },
        'reason': reason,
        'reportingComponent': f'ice.cheng/reconciler-{g_component}',
        'reportingInstance': f'{g_host}',
        'source': {
            'component': f'{g_component}',
            'host': f'{g_host}'
        },
        'type': type,
    }
    core_api.create_namespaced_event(namespace=namespace, body=body)


class SecretKeyRef:
    name: Optional[str] = None

    def parse(self, spec: dict, prefix: str) -> None:
        """Parse secret key reference from dictionary.

        Args:
            spec: Dictionary containing secret key reference
            prefix: Prefix for error messages

        Example spec:
        {
            "secretKeyRef": {
                "name": "my-secret"
            }
        }
        """
        if prefix in spec:
            sub_dict = get_dict(spec, prefix, prefix)
            self.name = get_str(sub_dict, "name", f"{prefix}.name")
        else:
            # Direct parsing if prefix is already the secretKeyRef part
            self.name = get_str(spec, "name", f"{prefix}.name")

    def validate(self, logger: Logger) -> None:
        if not self.name:
            raise SpecError("name is required for SecretKeyRef")


class KubernetesInterface(ABC):

    @abstractmethod
    def __init__(self):
        pass

    @property
    @abstractmethod
    def name(self) -> str:
        raise NotImplementedError("Subclasses should implement this method.")

    @property
    @abstractmethod
    def namespace(self) -> str:
        raise NotImplementedError("Subclasses should implement this method.")

    @abstractmethod
    def self_ref(self, field: Optional[str] = None) -> str:
        raise NotImplementedError("Subclasses should implement this method.")

    @abstractmethod
    def event_ref(self, field_path: Optional[str] = None) -> dict:
        """Return object reference for Kubernetes events.

        This method is specifically designed for use with Kubernetes Event API's
        involvedObject field, which requires namespace to be included.

        Args:
            field_path: Optional field path for the reference

        Returns:
            dict: Object reference with namespace for event involvedObject
        """
        raise NotImplementedError("Subclasses should implement this method.")

    def info(self, *, action: str, reason: str, msg: str, field: Optional[str] = None) -> None:
        post_event(self.namespace, self.event_ref(field),
                   type="Normal", action=action, reason=reason, msg=msg)

    def warn(self, *, action: str, reason: str, msg: str, field: Optional[str] = None) -> None:
        post_event(self.namespace, self.event_ref(field),
                   type="Warning", action=action, reason=reason, msg=msg)

    def error(self, *, action: str, reason: str, msg: str, field: Optional[str] = None) -> None:
        post_event(self.namespace, self.event_ref(field),
                   type="Error", action=action, reason=reason, msg=msg)
